"""
DynParamScroll.py --

This is thirt file of Dynamic mode window.

Date of creation: 2010-15-11

Copyright
Julian David Colorado, jd.colorado@upm.es
Universidad Politecnica de Madrid

See the file "license.terms" for information on usage and redistribution of this file, and for a
DISCLAIMER OF ALL WARRANTIES.
"""
import wx
import os, sys
from numpy import *
from systems import dcmotor
from eqtrad import *
from interface.paramvaluestree import *

#global variables.

#Windows
winxoffset =215
winyoffset = 10

#Linux
lnxxoffset =305
lnxyoffset = 10

radstodeg = (180/pi)
degtorads = (pi/180)
FALSE = 0
TRUE = 1


class DynParamScroll( wx.ScrolledWindow ):
	"""Main frame holding the Dynamic Paramaters scroll."""
	def __init__(self, parent, id, pos, size):
		"""Creates the main scroll frame, the graphical description window."""
		wx.ScrolledWindow.__init__(self, parent, id, style=wx.SUNKEN_BORDER )

		#storage variables
		self.systemtype = "none"

		#Entries widgets.
		#Tree Input Item.
		if (os.name=='nt'):
			self.ItemInput = wx.TextCtrl( self, -1, '',  size=(65, 25), style=wx.TE_RIGHT | wx.TE_PROCESS_ENTER )
		else:
			self.ItemInput = wx.TextCtrl( self, -1, '',  size=(85, 25), style=wx.TE_RIGHT | wx.TE_PROCESS_ENTER )

		self.ItemInput.Bind(wx.EVT_TEXT_ENTER, self.OnEnterValue )
		self.ItemInput.Hide()

		#Tree Open Item
		self.Open=wx.BitmapButton(self, wx.NewId(), wx.Bitmap('interface/images/open.png'), wx.DefaultPosition, wx.Size(38, 30))
		self.Bind(wx.EVT_BUTTON, self.OnOpen, self.Open )
		self.Open.Hide()

		#Tree Combo box Item
		self.ODEtypes = [ 'euler', 'improvedeuler', 'rungekutta' ]
		self.ComboBox = wx.ComboBox(self, -1, pos=(50, 170), size=(120, 25), choices=self.ODEtypes, style=wx.CB_READONLY)
		self.Bind(wx.EVT_COMBOBOX, self.OnSelect,self.ComboBox)
		self.ComboBox.Hide()

		#Number of controllers
		self.ContNum = [ 'Open-Loop',  'Morphing Control', 'Flap+Morphing Control' ]
		self.ComboBoxctrl = wx.ComboBox(self, -1, pos=(50, 170), size=(120, 25), choices=self.ContNum, style=wx.CB_READONLY)
		self.Bind(wx.EVT_COMBOBOX, self.OnSelectctrl,self.ComboBoxctrl)
		self.ComboBoxctrl.Hide()

		#Dynamic parameters ctrl tree
		self.ParamValuesTree = ParamValuesTree( self, -1)
		self.ParamValuesTree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, self.ParamValuesTree )

		# Set the scrolling rate; use same value in both horizontal and vertical directions.
		scrollRate = 1
		self.SetScrollRate(scrollRate, scrollRate)
		self.SetBackgroundColour("white")
		self.SetScrollbars(20,20,10,20)




	def GetSystemValues( self, system ):
		"""Gets the loaded system values in order to manipulate them"""
		self.system = system
		self.systemtype = system.type
		self.simtime = self.system.finaltime
		self.system.x1=1
		self.system.x2=2
		self.system.dx1=3
		self.system.dx2=4
		self.ParamValuesTree.UpdateTreeCtrlInfo( self.system )

	def GetTitleString ( self ):
		"""It returns title string."""
		self.splittext = self.text.split(':') #split string into key word list.
		self.splittext = self.splittext[0]+':'

	def  SetItemInput ( self, x, y ):
		""" Clears and hides the ItemInput dialog"""
		self.Open.Hide()
		self.ComboBox.Hide()
		self.ComboBoxctrl.Hide()
		self.ItemInput.SetPosition( (x, y) )
		self.ItemInput.Clear()
		self.ItemInput.Show()

	def OnSelChanged(self, event):
		"""Changes the sub-menu according to option given by the user."""

		# Getting the mouse position
		(windowx, windowy) = wx.GetMousePosition()
		(x, y) = self.ScreenToClientXY(windowx, windowy)

		#Getting the Tree item
		item =  event.GetItem()
		self.text = self.ParamValuesTree.GetItemText(item)

		#Displays value according to option selected.
		if self.systemtype != "none":
			self.GetTitleString()
			#Dynamic Params.
			#bats
			if(os.name=='nt'):
				xoffset=winxoffset
				yoffset=winyoffset
			else:
				xoffset=lnxxoffset
				yoffset=lnxyoffset

			#if ( self.splittext == 'Body Mass:'):
				#self.SetItemInput( xoffset, (y - yoffset) )
				#self.ItemInput.WriteText('%.5f' %self.system.Mb )
			if ( self.splittext == 'Humerus Mass:'):
				self.SetItemInput( xoffset, (y - yoffset) )
				self.ItemInput.WriteText('%.5f' %self.system.M )
			elif ( self.splittext == 'Radius Mass:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.m )
			elif ( self.splittext == 'Humerus Lenght:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.K )
			elif ( self.splittext == 'Radius Lenght:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.p )
			#batwings's
			elif ( self.splittext == 'Mass:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.m )
			elif ( self.splittext == 'Inertia:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.Pend2Ine )
			elif ( self.splittext == 'Friction:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.Pend2fric )

			#Any system
			elif ( self.splittext == 'Gravity:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.2f' %self.system.grav )
			#DC Motor Params.
			#DC motor 1
			elif ( self.splittext == 'Ka:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.dcmotor.Ka )
			elif ( self.splittext == 'Ta:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.dcmotor.Ta )
			#DC motor 2 and DC motor 3
			elif ( self.splittext == 'Rsma:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.dcmotor.R )
			elif ( self.splittext == 'rsma:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.dcmotor.r )
			elif ( self.splittext == 'Lsma:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.dcmotor.Km )
			elif ( self.splittext == 'hsma:'):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.dcmotor.Kg )

			#Dynamic Model, Motor Model, swing up, controller
			elif ( self.splittext == 'Bat Model:') or ( self.splittext == 'Actuation Model:') or ( self.splittext == 'Swing Up:' ) or ( self.splittext == 'Controller:' )or ( self.splittext == 'Matlab File:' ):
				self.Open.SetPosition( (xoffset, y - yoffset) )
				self.Open.Show()
				self.ItemInput.Hide()
				self.ComboBox.Hide()
				self.ComboBoxctrl.Hide()
			#Swing up order
			elif ( self.splittext == 'Swing Up Order:' ):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.swinguporder )
			#Controller order
			elif ( self.splittext == 'Controller Order:' ):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.ctrlorder )
			#Controller Setup
			elif ( self.splittext == 'Controller Setup:' ):
				self.ComboBoxctrl.SetPosition( (xoffset-40, y - yoffset) )
				self.ComboBoxctrl.Show()
				self.ComboBox.Hide()
				self.ItemInput.Hide()
				self.Open.Hide()
			#Control step time
			elif ( self.splittext == 'Control Step Time:' ):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.ctrlstep )
			#Controller switch range
			elif ( self.splittext == 'Control Switch Range:' ):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText( '%.2f' %(self.system.range*radstodeg ) )
			#ODE Solver
			elif ( self.splittext == 'ODE Solver:' ):
				self.ComboBox.SetPosition( (xoffset-40, y - yoffset) )
				self.ComboBox.Show()
				self.ComboBoxctrl.Hide()
				self.ItemInput.Hide()
				self.Open.Hide()
			#Integrator step time
			elif ( self.splittext == 'Step Time:' ):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.5f' %self.system.integstep)
			#Total simulation time
			elif ( self.splittext == 'Simulation Time:' ):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%.2f' %self.system.finaltime)
			#Matlab Options
			elif ( self.splittext == 'X1:' ):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%d' %self.system.x1)
			elif ( self.splittext == 'X2:' ):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%d' %self.system.x2)
			elif ( self.splittext == 'dX1:' ):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%d' %self.system.dx1)
			elif ( self.splittext == 'dX2:' ):
				self.SetItemInput( xoffset, y - yoffset )
				self.ItemInput.WriteText('%d' %self.system.dx2)
			else:
				self.ItemInput.Hide()
				self.Open.Hide()
				self.ComboBox.Hide()
				self.ComboBoxctrl.Hide()

	def OnEnterValue(self, event):
		""" It proccess input data and updates class instance values"""
		input = (float)(self.ItemInput.GetValue())
		self.GetTitleString()
		#Dynamic Params.
		#bat's
		#if ( self.splittext == 'Body Mass:'):
			#self.ParamValuesTree.SetItemText(self.ParamValuesTree.dynitem[0], 'Body Mass: %f Kg' %(float)(input) )
			#self.system.M = (float)(input)
		if ( self.splittext == 'Humerus Mass:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.dynitem[0], 'Humerus Mass: %f Kg' %(float)(input) )
			self.system.M = (float)(input)
		elif ( self.splittext == 'Radius Mass:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.dynitem[1], 'Radius Mass: %f Kg' %(float)(input) )
			self.system.m = (float)(input)
		elif ( self.splittext == 'Humerus Lenght:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.dynitem[2], 'Humerus Lenght: %f' %(float)(input) )
			self.system.K = (float)(input)
		elif ( self.splittext == 'Radius Lenght:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.dynitem[3], 'Radius Lenght: %f' %(float)(input) )
			self.system.p = (float)(input)
		#batwing's
		elif ( self.splittext == 'Mass:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.dynitem[0], 'Mass: %f Kg' %(float)(input) )
			self.system.m = (float)(input)
		elif ( self.splittext == 'Inertia:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.dynitem[1], 'Inertia: %f Kg.m^2' %(float)(input) )
			self.system.Pend2Ine = (float)(input)
		elif ( self.splittext == 'Friction:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.dynitem[2], 'Friction: %f' %(float)(input) )
			self.system.Pend2fric = (float)(input)

		#Any System
		elif ( self.splittext == 'Gravity:'):
			if ( self.systemtype == 'batwing'):
				self.ParamValuesTree.SetItemText(self.ParamValuesTree.dynitem[3], 'Gravity: %.2f m/s^2' %(float)(input) )
			else:
				self.ParamValuesTree.SetItemText(self.ParamValuesTree.dynitem[4], 'Gravity: %.2f m/s^2' %(float)(input) )
			self.system.grav = (float)(input)
		#DC Motor Params.
		#DC motor 1
		elif ( self.splittext == 'Ka:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.motoritem[0], 'Ka: %f' %(float)(input) )
			self.system.dcmotor.Ka = (float)(input)
		elif ( self.splittext == 'Ta:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.motoritem[1], 'Ta: %f' %(float)(input) )
			self.system.dcmotor.Ta = (float)(input)
		#DC motor 2 and DC motor 3
		elif ( self.splittext == 'Rsma:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.motoritem[0], 'Rsma: %f m' %(float)(input) )
			self.system.dcmotor.R = (float)(input)
		elif ( self.splittext == 'rsma:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.motoritem[1], 'rsma: %f m' %(float)(input) )
			self.system.dcmotor.r = (float)(input)
		elif ( self.splittext == 'Lsma:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.motoritem[2], 'Lsma: %f' %(float)(input) )
			self.system.dcmotor.Km = (float)(input)
		elif ( self.splittext == 'hsma:'):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.motoritem[3], 'hsma: %f' %(float)(input) )
			self.system.dcmotor.Kg = (float)(input)

		#Swing up order
		elif ( self.splittext == 'Swing Up Order:' ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.controlitem[5], 'Swing Up Order: %f' %(float)(input) )
			self.system.swinguporder = (float)(input)
		#Controller order
		elif ( self.splittext == 'Controller Order:' ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.controlitem[1], 'Controller Order: %f' %(float)(input) )
			self.system.ctrlorder = (float)(input)
		#Control step time
		elif ( self.splittext == 'Control Step Time:' ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.controlitem[2], 'Control Step Time: %f ms' %(float)(input) )
			self.system.ctrlstep = (float)(input)
		#Controller switch range
		elif ( self.splittext == 'Control Switch Range:' ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.controlitem[3], 'Control Switch Range: %.2f deg' %(float)(input) )
			self.system.range = (float)(input*degtorads)
		#Integrator step time
		elif ( self.splittext == 'Step Time:' ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.integstep, 'Step Time: %f ms' %(float)(input) )
			self.system.integstep = (float)(input)
		#Total simulation time
		elif ( self.splittext == 'Simulation Time:' ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.time, 'Simulation Time: %f s' %(float)(input) )
			self.system.finaltime = (float)(input)
		#Matlab Options
		elif ( self.splittext == 'X1:' ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.x1, 'X1: %d' %(int)(input) )
			self.system.x1 = (int)(input)
		elif ( self.splittext == 'X2:' ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.x2, 'X2: %d' %(int)(input) )
			self.system.x2 = (int)(input)
		elif ( self.splittext == 'dX1:' ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.dx1, 'dX1: %d' %(int)(input) )
			self.system.dx1 = (int)(input)
		elif ( self.splittext == 'dX2:' ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.dx2, 'dX2: %d' %(int)(input) )
			self.system.dx2 = (int)(input)

		self.system.SolutionComputed = FALSE

	def OnSelect(self, event):
		""" It proccess ComboBox data and shows selected value"""
		item = event.GetSelection()
		if ( item == 0 ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.integr, 'ODE Solver: euler' )
			self.system.odesolver = 'euler'
			self.system.MakefileGenerated = FALSE
		elif ( item == 1 ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.integr, 'ODE Solver: improvedeuler' )
			self.system.odesolver = 'improvedeuler'
			self.system.MakefileGenerated = FALSE
		elif ( item == 2 ):
			self.ParamValuesTree.SetItemText(self.ParamValuesTree.integr, 'ODE Solver: rungekutta' )
			self.system.odesolver = 'rungekutta'
			self.system.MakefileGenerated = FALSE

		self.ComboBox.Hide()

	def OnSelectctrl(self, event):
		""" It proccess ComboBox data and shows selected value"""
		item = event.GetSelection()
		if ( item == 0 ):
			self.system.control1=''
			self.system.control2=''
			self.ParamValuesTree.UpdateControllerTreeInfo(0)
			self.system.ctrlnum=0
		elif ( item == 1 ):
			self.ParamValuesTree.UpdateControllerTreeInfo(1)
			self.system.ctrlnum=1
		elif ( item == 2 ):
			self.ParamValuesTree.UpdateControllerTreeInfo(2)
			self.system.ctrlnum=2

		self.ComboBoxctrl.Hide()

	def OnOpen(self, event ):
		"""Loads a new sub-tree depending on option selected by the user"""
		dir = os.getcwd()
		if ( self.splittext == 'Bat Model:'):
			dir = os.path.join(dir, 'dynmodels/'+self.systemtype)
		elif ( self.splittext == 'Actuation Model:'):
			dir = os.path.join(dir, 'dynmodels/dcmotors')
		elif ( self.splittext == 'Swing Up:') or ( self.splittext == 'Controller:'):
			dir = os.path.join(dir, 'controlaws/'+self.systemtype)
		elif ( self.splittext == 'Matlab File:'):
			dir = os.path.join(dir, 'matlab/'+self.systemtype)

		dlg = wx.FileDialog(self, "Choose a file", dir, "", "*.cpp;*.eqv;*.txt",wx.OPEN)

		if dlg.ShowModal() == wx.ID_OK:
			try:
				path=dlg.GetPath()
				file = os.path.basename(path)
				(file, ext) = os.path.splitext(file)
				if ( self.splittext == 'Actuation Model:'):
					self.ParamValuesTree.UpdateMotorTreeInfo( self.system,  self.systemtype, file )
				if ( self.splittext == 'Swing Up:'):
					if(ext!='.cpp'):
						eqtrad_main(path,2,self.systemtype,self.system.motor)
					self.ParamValuesTree.SetItemText( self.ParamValuesTree.controlitem[4], 'Swing Up: %s' %file )
					self.system.control2 = file
					self.system.MakefileGenerated = FALSE
				if ( self.splittext == 'Controller:'):
					if(ext!='.cpp'):
						eqtrad_main(path,1,self.systemtype,self.system.motor)
					self.ParamValuesTree.SetItemText( self.ParamValuesTree.controlitem[0], 'Controller: %s' %file )
					self.system.control1 = file
					self.system.MakefileGenerated = FALSE
				if ( self.splittext == 'Matlab File:'):
					self.ParamValuesTree.SetItemText( self.ParamValuesTree.matlab, 'Matlab File: %s' %file )
					self.system.matlab = file
					self.system.SolutionComputed = FALSE

			except IOError, error:
				error_dlg = wx.MessageDialog(self, 'Error opening file\n' + str(error))
				error_dlg.ShowModal()
		dlg.Destroy()

